
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'


function PromiseZ(exector) {
    //  初始化Promise的属性 ， 包括 status 、value、 reason 、 fulfilledCallback 以及 rejectCallback
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.fulfilledCallback = [];
    this.rejectCallback = [];

    //  分别实现 resolve 、 reject函数
    //  当 status === PENDING 时才可以执行 resolve内部的代码，确保status 状态只会从 PENDING ====> FULFILLED 或PENDING ====> REJECTED 
    const self = this;
    function resolve(value) {
        if (self.status === PENDING) {
            self.status = FULFILLED;
            self.value = value;

            self.fulfilledCallback.forEach((cb) => {
                cb && cb(value)
            })
        }
    }
    function reject(reason) {
        if (self.status === PENDING) {
            self.status = REJECTED;
            self.reason = reason;
            self.rejectCallback.forEach((cb) => {
                cb && cb(reason)
            })
        }
    }

    //  exector 会有两个参数 ， 均为函数 即 resolve 、reject
    //  且在执行exector时可能报错，也要被 reject 捕获
    try {
        exector(resolve, reject)
    } catch (e) {
        reject(e)
    }
}

//  then 是 promise的实例上的方法 ， 且会返回一个新的Promise的实例 ，且不能为同一个Promise对象，因为 Promise的对象在then之后状态就已经改变了，不能再改变了 ， 所以不能返回this
//  then 接收 Promise 返回

PromiseZ.prototype.then = function (onFulfilled, onRejected) {
    let _this = this;
    let permise2;
    //  then 接受两个参数 ， 分别为成功回调与失败回调
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => { return value }
    onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason }
    //  status 有三种状态 ，所以 会有三个可能
    if (_this.status === FULFILLED) {
        return promise2 = new PromiseZ((resolve, reject) => {
            setTimeout(()=>{
                  //  如果 返回值为 promise对象 则 promise2 直接等于这个promise
                try {
                    const x = onFulfilled(_this.value)
                    if (x instanceof PromiseZ) {
                        x.then(resolve, reject)
                    }
                    resolve(x)
                } catch (e) {
                    reject(e)
                }
            })
        })
    } else if (_this.status === REJECTED) {
        return promise2 = new PromiseZ((resolve, reject) => {
            setTimeout(()=>{
                try {
                    const x = onRejected(_this.value)
                    if (x instanceof PromiseZ) {
                        x.then(resolve, reject)
                    }
                    reject(x)
                } catch (e) {
                    reject(e)
                }
            })
        })
    } else {
        return promise2 = new PromiseZ((resolve, reject) => {
            //  如果此时 还未完成状态改变，则将传入的函数加到 promise 的函数回调队列中去
            _this.fulfilledCallback.push(function (value) {
              
                try {
                    const x = onFulfilled(value)
                    if (x instanceof PromiseZ) {
                        x.then(resolve, reject)
                    }
                    resolve(x)
                } catch (e) {
                    reject(e)
                }
          
            })
            _this.rejectCallback.push((reason) => {
                try {
                    const x = onRejected(reason)
                    if (x instanceof PromiseZ) {
                        x.then(resolve, reject)
                    }
                    reject(x)
                } catch (e) {
                    reject(e)
                }
            })
        })
    }

}



// new PromiseZ((resolve, reject) => {
//     let i = 0
//     setInterval(()=>{
//         i++
//         resolve(i)
//     },1000);
// }).then(res => {
//     console.log(res);
// })

// PromiseZ.prototype.catch = function (onRejected) {
//     return this.then(null, onRejected)
// }

// const promise23 = new PromiseZ((resolve, reject) => {
//     resolve(11)
// }).then().catch().then(res => {
//     console.log(res);
// })

console.log(1);
new PromiseZ((resolve,reject)=>{
    console.log(2);
    resolve()
    console.log(3);
}).then(res=>{
    console.log(4);
})

console.log(5);